package com.m1905.lib.download.task;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import com.m1905.lib.download.db.DBManager;
import com.m1905.lib.download.listener.RequestListener;
import com.m1905.lib.download.listener.RequestTaskListener;
import com.m1905.lib.download.model.DownloadDBItem;
import com.m1905.lib.download.model.State;
import com.m1905.lib.download.request.BaseDownloadRequest;
import com.m1905.lib.download.request.StopException;
import com.m1905.lib.download.util.DLog;
import com.m1905.lib.download.util.DownloadPreferences;


/**
 * @author wanghao
 * @date 2022/8/4.
 * @des
 */
public class DownloadTask extends BaseTask implements RequestListener {

    public final static int UPDATE_WAITING = 0;
    public final static int UPDATE_START = 1;
    public final static int UPDATE_LOADING = 2;
    public final static int UPDATE_FAILURE = 3;
    public final static int UPDATE_SUCCESS = 4;
    public final static int UPDATE_FILE_SIZE = 5;
    public final static int UPDATE_CANCEL = 6;
    public final static int UPDATE_DELETE = 7;

    private volatile int mState = State.WAITING;

    private final Handler mHandler;
    private Looper mLooper;
    private final RequestTaskListener callBack;

    public DownloadTask(Looper looper, RequestTaskListener callBack) {
        this.callBack = callBack;
        mLooper = looper;
        mHandler = new Handler(looper) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (msg.obj instanceof Object[]) {
                    onProgressUpdate((Object[]) msg.obj);
                } else {
                    onProgressUpdate(msg.obj);
                }

            }
        };
    }

    public void startDownload(String urlStr, String fileSavePath, long totalSize, boolean autoResume) {
        DLog.e("DownloadTask startDownload mState: " + mState + " url:" + urlStr + " \nfilePath:" + fileSavePath + "\nautoResume:" + autoResume);
        if (mState != State.WAITING) {
            return;
        }
        this.publishProgress(UPDATE_START);
        BaseDownloadRequest request = DownloadPreferences.getRequestFactory().createRequest();
        request.download(fileSavePath, urlStr, totalSize, autoResume, this);
    }


    @Override
    public void onFileSize(long total) {
        publishProgress(UPDATE_FILE_SIZE, total);
    }

    @Override
    public void onProgress(long total, long current, long speed) {
        publishProgress(UPDATE_LOADING, total, current, speed);
    }

    @Override
    public void onCompleted() {
        publishProgress(UPDATE_SUCCESS);
    }

    // 主线程中执行
    protected void onProgressUpdate(Object... values) {
        if (values == null || values.length == 0 || callBack == null)
            return;
        DLog.e("DownloadTask onProgressUpdate start from:" + mState + "  to:" + getStatus((Integer) values[0]));
        int state = (int) values[0];

        switch (state) {
            case UPDATE_WAITING:
                mState = State.WAITING;
                callBack.onWaiting((boolean) values[1]);
                break;
            case UPDATE_START:
                if (mState == State.CANCELLED || mState == State.DELETE) {
                    return;
                }
                mState = State.STARTED;
                callBack.onStart();
                break;
            case UPDATE_LOADING:
                if (mState == State.CANCELLED || mState == State.DELETE) {
                    return;
                }
                mState = State.LOADING;
                callBack.onLoading((long) values[1], (long) values[2], (long) values[3]);
                break;
            case UPDATE_FAILURE:
                if (mState == State.CANCELLED || mState == State.DELETE) {
                    return;
                }
                mState = State.FAILURE;
                callBack.onFailure((int) values[1], (String) values[2]);
                break;
            case UPDATE_SUCCESS:
                if (mState == State.DELETE) {
                    return;
                }
                mState = State.SUCCESS;
                callBack.onSuccess();
                break;
            case UPDATE_FILE_SIZE:
                callBack.onFileSize((long) values[1]);
                break;
            case UPDATE_CANCEL:
                mState = State.CANCELLED;
                callBack.onCancel();
                break;
            case UPDATE_DELETE:
                mState = State.DELETE;
                callBack.onDelete();
                break;
        }
    }

    // 取消下载
    public void cancel() {
        DLog.e("DownloadTask cancel " + mState);
        //回调到主线程
        if (mState < State.FAILURE) {
            publishProgress(UPDATE_CANCEL);
        }
        abortedRequest();
    }

    // 删除下载
    public void delete() {
        //回调到主线程
        DLog.e("DownloadTask delete " + mState);
        if (mState != State.DELETE) {
            publishProgress(UPDATE_DELETE);
        }
        abortedRequest();
    }

    // 进入等待状态，未添加保存下载任务到数据库，已添加则更新下载状态到Waiting
    public boolean preWaiting(DownloadDBItem downloadItem) {
        DLog.e("DownloadTask waiting " + mState);
        if (downloadItem.getId() <= 0) {
            long id = DBManager.insertToDatabase(downloadItem);
            if (id > 0) {
                downloadItem.setId(id);
            } else {
                // 插入数据库失败，放弃下载
                DLog.e("DownloadTask waiting insert failure");
                return false;
            }
        }
        return true;
    }

    public void waiting(boolean insert) {
        publishProgress(UPDATE_WAITING, insert);
    }

    private void publishProgress(Object... values) {
        DLog.e("DownloadTask publishProgress " + getStatus((int)values[0]) + "   " + values.length + "  " + Thread.currentThread().getName());
        if (Looper.myLooper() == mLooper) {
            onProgressUpdate(values);
        } else {
            Message message = Message.obtain();
            message.obj = values;
            mHandler.sendMessage(message);
        }
    }


    @Override
    public void run() {
        try {
            super.run();
        } catch (StopException e) {
//            e.printStackTrace();
            DLog.e("DownloadTask startDownload: " + e);
            publishProgress(UPDATE_FAILURE, e.getErrorCode(), e.getMessage());
        } catch (Exception e) {
//            e.printStackTrace();
            DLog.e("DownloadTask startDownload: " + e.getMessage());
            publishProgress(UPDATE_FAILURE, -1, e.getMessage());
        }

    }

    private String getStatus(int status) {
        switch (status) {
            case UPDATE_WAITING:
                return "WAITING";
            case UPDATE_START:
                return "START";
            case UPDATE_LOADING:
                return "LOADING";
            case UPDATE_FAILURE:
                return "FAILURE";
            case UPDATE_SUCCESS:
                return "SUCCESS";
            case UPDATE_FILE_SIZE:
                return "FILE_SIZE";
            case UPDATE_CANCEL:
                return "CANCEL";
            case UPDATE_DELETE:
                return "DELETE";
        }
        return "UnKnow " + status;
    }

}
